﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Smart.Web.Mobile
{
    /// <summary>
    /// 
    /// </summary>
    public class MobileSJISEncoding : MobileEncoding
    {
        private readonly Dictionary<char, byte[]> unicodeToSjis;
        private readonly Dictionary<int, char> sjisToUnicode;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pictgramTreat"></param>
        /// <param name="unicodeToSjis"></param>
        /// <param name="sjisToUnicode"></param>
        public MobileSJISEncoding(PictgramTreat pictgramTreat, Dictionary<char, byte[]> unicodeToSjis, Dictionary<int, char> sjisToUnicode) :
            base( Encoding.GetEncoding( "Shift_JIS" ), pictgramTreat )
        {
            this.unicodeToSjis = unicodeToSjis;
            this.sjisToUnicode = sjisToUnicode;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="chars"></param>
        /// <param name="charIndex"></param>
        /// <param name="charCount"></param>
        /// <param name="bytes"></param>
        /// <param name="byteIndex"></param>
        /// <returns></returns>
        protected override int GetMobileBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
        {
            int length = 0;
            int start = 0;
            int end = 0;

            for( int i = 0; i < charCount; i++ )
            {
                char c = chars[ charIndex + i ];
                byte[] cb;
                if( this.unicodeToSjis.TryGetValue( c, out cb ) )
                {
                    // 未処理分
                    if( end > start )
                    {
                        length += BaseEncoding.GetBytes( chars, start, end - start, bytes, length );
                    }

                    // 変換
                    foreach( byte b in cb )
                    {
                        bytes[ length ] = b;
                        length++;
                    }

                    // 開始位置リセット
                    start = i + 1;
                    end = start;
                }
                else
                {
                    // 文字継続
                    end += 1;
                }
            }

            // 残り
            if( end > start )
            {
                length += BaseEncoding.GetBytes( chars, start, end - start, bytes, length );
            }

            return length;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="byteIndex"></param>
        /// <param name="byteCount"></param>
        /// <param name="chars"></param>
        /// <param name="charIndex"></param>
        /// <returns></returns>
        protected override int GetMobileChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
        {
            int length = 0;
            int start = 0;
            int end = 0;

            for( int i = 0; i < byteCount; i++ )
            {
                byte b = bytes[ byteIndex + i ];

                if ( ( ( ( 0x81 <= b ) && ( b <= 0x9f ) ) || ( ( 0xe0 <= b ) && ( b <= 0xfc ) ) ) &&
                     ( i < byteCount - 1 ) )
                {
                    // 2バイト文字
                    int index = ( b << 8 ) + bytes[ byteIndex + i + 1 ];
                    char c;
                    if( this.sjisToUnicode.TryGetValue( index, out c ) )
                    {
                        // 未処理分
                        if( end > start )
                        {
                            length += BaseEncoding.GetChars( bytes, start, end - start, chars, length );
                        }

                        // 絵文字
                        chars[ length ] = c;
                        length++;

                        // 絵文字以外開始位置リセット
                        start = i + 2;
                        end = start;
                    }
                    else
                    {
                        // 絵文字以外
                        end += 2;
                    }

                    i++;
                }
                else
                {
                    // 1バイト文字
                    end += 1;
                }
            }

            // 残り
            if( end > start )
            {
                length += BaseEncoding.GetChars( bytes, start, end - start, chars, length );
            }

            return length;
        }
    }
}
